<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue 3 表单页面</title>
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css" />
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script src="https://unpkg.com/element-plus"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>


  <style>
    .form-row {
      display: flex;
      gap: 20px;
      margin-bottom: 20px;
    }
    .form-item {
      flex: 1;
      display: flex;
      flex-direction: column;
    }
    .form-label {
      margin-bottom: 6px;
      font-weight: bold;
      display: inline-block;
    }
    .form-container {
      max-width: 900px;
      margin: 40px auto;
      padding: 30px;
      border: 1px solid #eee;
      border-radius: 8px;
      box-shadow: 0 2px 12px rgba(0,0,0,0.05);
      background-color: #fff;
    }
    .el-input,
    .el-input-number,
    .el-select,
    .el-textarea {
      width: 100%;
    }
    .button-row {
      display: flex;
      justify-content: center;
      gap: 20px;
      margin-top: 20px;
    }
    h2 {
      font-size: 20px;
      margin-bottom: 10px;
      color: #333;
    }
  </style>
</head>
<body>
<div id="app">
  <div class="form-container">
    <!-- 参数设置 -->
    <h2>参数设置</h2>

    
    <div class="form-row">
      <div class="form-item">
        <label class="form-label">模型类型</label>
        <el-select v-model="selectValue" placeholder="请选择">
          <el-option label="opt" value="opt"></el-option>
          <el-option label="llama" value="llama"></el-option>
          <el-option label="gpt" value="gpt"></el-option>
        </el-select>
      </div>
      <div class="form-item">
        <label class="form-label">Length</label>
        <el-input v-model="length" placeholder="Length" @input="validateFloat('length')"></el-input>
      </div>
    </div>

    <div class="form-row">
      <div class="form-item">
        <label class="form-label">精度</label>
        <el-select v-model="precision" placeholder="选择精度">
          <el-option label="fp16" value="fp16"></el-option>
          <!-- <el-option label="fp32" value="fp32"></el-option> -->
        </el-select>
      </div>
    </div>

    <div class="form-row">
      <div class="form-item">
        <label class="form-label">模式</label>
        <el-select v-model="mode" placeholder="请选择模式">
          <el-option label="heavy" value="heavy"></el-option>
          <el-option label="recent" value="recent"></el-option>
          <el-option label="stride" value="stride"></el-option>
        </el-select>
      </div>
    </div>

    <div class="form-row">
      <div class="form-item" v-if="mode === 'heavy'">
        <label class="form-label">Heavy ratio</label>
        <el-input v-model="heavyratio" placeholder="Heavy ratio" @input="validateFloat('heavyratio')"></el-input>
      </div>
      <div class="form-item" v-if="mode === 'recent'">
        <label class="form-label">Recent ratio</label>
        <el-input v-model="recentratio" placeholder="Recent ratio" @input="validateFloat('recentratio')"></el-input>
      </div>
      <div class="form-item" v-if="mode === 'stride'">
        <label class="form-label">Stride</label>
        <el-input-number v-model="stride" :min="1" :step="1" controls-position="right"></el-input-number>
      </div>
    </div>

    <div class="form-item">
      <label class="form-label">输入</label>
      <el-input type="textarea" v-model="inputText" :rows="4" placeholder="请输入内容"></el-input>
    </div>

    <div class="button-row">
      <el-button type="primary" @click="submitForm">提交</el-button>
      <el-button type="default" @click="resetForm">取消</el-button>
    </div>

    <el-divider content-position="center">结果展示</el-divider>

    
    <div id="result-area">
      <div class="form-row">
        <div class="form-item">
          <label class="form-label">Original</label>
          <el-input type="textarea" v-model="originalInfo" readonly :rows="3" placeholder="Original result"></el-input>
        </div>
        <div class="form-item">
          <label class="form-label">Optimize</label>
          <el-input type="textarea" v-model="optimizeInfo" readonly :rows="3" placeholder="Optimized result"></el-input>
        </div>
      </div>

      <div style="height: 200px; width: 100%; margin-top: 20px;">
        <canvas id="result-chart"></canvas>
      </div>
    </div>
  </div>
</div>

<script>
const { createApp, ref, onMounted } = Vue;
const { ElLoading } = ElementPlus;

createApp({
  setup() {
    const selectValue = ref('');
    const length = ref('');
    const batchSize = ref(1);
    const stride = ref(1);
    const heavyratio = ref('');
    const recentratio = ref('');
    const inputText = ref('');
    const mode = ref('');
    const precision = ref('');
    const originalInfo = ref('');
    const optimizeInfo = ref('');
    let chartInstance = null;

    function validateFloat(field) {
      if (!/^\d*\.?\d*$/.test(eval(field).value)) {
        eval(field).value = eval(field).value.replace(/[^\d.]/g, '').replace(/(\..*)\./g, '$1');
      }
    }

    function renderChart(latencyData, memoryData, bleuData) {
      const ctx = document.getElementById('result-chart');
      if (chartInstance) chartInstance.destroy();

      chartInstance = new Chart(ctx, {
        type: 'bar',
        data: {
          labels: ['origin', 'optimized'],
          datasets: [
            {
              label: 'Latency (s)',
              data: latencyData,
              backgroundColor: 'rgba(255, 99, 132, 0.8)',
              yAxisID: 'y-latency'
            },
            {
              label: 'KV cache memory (MB)',
              data: memoryData,
              backgroundColor: 'rgba(54, 162, 235, 0.8)',
              yAxisID: 'y-memory'
            },
            {
              label: 'BLEU score',
              data: bleuData,
              backgroundColor: 'rgba(75, 192, 192, 0.8)',
              yAxisID: 'y-bleu'
            }
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          scales: {
            'y-latency': {
              type: 'linear',
              position: 'left',
              beginAtZero: true,
              title: { display: true, text: 'Latency (s)', color: 'rgba(255, 99, 132, 1)' },
              ticks: { color: 'rgba(255, 99, 132, 1)' },
              grid: { drawOnChartArea: true, color: 'rgba(255, 99, 132, 0.1)' }
            },
            'y-memory': {
              type: 'linear',
              position: 'right',
              beginAtZero: true,
              title: { display: true, text: 'KV cache memory (MB)', color: 'rgba(54, 162, 235, 1)' },
              ticks: { color: 'rgba(54, 162, 235, 1)' },
              grid: { drawOnChartArea: false }
            },
            'y-bleu': {
              type: 'linear',
              position: 'right',
              beginAtZero: true,
              min: 0,
              max: 100,
              title: { display: true, text: 'BLEU score', color: 'rgba(75, 192, 192, 1)' },
              ticks: { color: 'rgba(75, 192, 192, 1)', stepSize: 0.2 },
              grid: { drawOnChartArea: false }
            },
            x: {
              grid: { display: false }
            }
          },
          plugins: {
            legend: {
              position: 'top',
              labels: {
                usePointStyle: true,
                padding: 20
              }
            },
            tooltip: {
              mode: 'index',
              intersect: false
            },
            datalabels: {
              anchor: 'end',
              align: 'end',
              color: '#000',
              offset: -10,
              font: {
                weight: 'bold'
              },
              formatter: function(value) {
                return value.toFixed(2);
              }
            }
          }
        },
        plugins: [ChartDataLabels],
      });
    }

    function submitForm() {
      const payload = {
        selectValue: selectValue.value,
        length: length.value,
        batchSize: batchSize.value,
        stride: stride.value,
        heavyratio: heavyratio.value,
        recentratio: recentratio.value,
        inputText: inputText.value,
        mode: mode.value,
        precision: precision.value
      };

      console.log("提交数据：", payload);

      // 开启loading
      const loading = ElLoading.service({
        target: document.getElementById('result-area'),
        lock: true,
        text: '推理中，请稍候...',
        background: 'rgba(255, 255, 255, 0.8)'
      });

      axios.post('api/getllmres/', payload)
        .then(res => {
          console.log('提交成功', res.data);
          const latency = [res.data.ori[1], res.data.opt[1]];
          const memory = [res.data.ori[2], res.data.opt[2]];
          const bleu = [res.data.ori[3], res.data.opt[3]];  // 假设BLEU得分在第4个位置
          renderChart(latency, memory, bleu);
          originalInfo.value = res.data.ori[0];
          optimizeInfo.value = res.data.opt[0];
        })
        .catch(err => {
          console.error('提交失败', err);
        })
        .finally(() => {
          loading.close(); //  关闭 loading
        });
    }

    function resetForm() {
      selectValue.value = '';
      length.value = '';
      batchSize.value = 1;
      stride.value = 1;
      heavyratio.value = '';
      recentratio.value = '';
      inputText.value = '';
      mode.value = '';
      precision.value = '';
      originalInfo.value = '';
      optimizeInfo.value = '';
      renderChart([0, 0], [0, 0], [0, 0]);
    }

    onMounted(() => {
      renderChart([0, 0], [0, 0], [0, 0]);
    });

    return {
      selectValue,
      length,
      batchSize,
      stride,
      heavyratio,
      recentratio,
      inputText,
      validateFloat,
      submitForm,
      resetForm,
      mode,
      precision,
      originalInfo,
      optimizeInfo
    };
  }
}).use(ElementPlus).mount('#app');
</script>
</body> 
</html>